package web.eshop;

import domain.ImageEntry;
import domain.shop.Attribute;
import domain.shop.Product;
import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.wicketstuff.annotation.mount.MountPath;
import org.wicketstuff.annotation.strategy.MountIndexedParam;
import service.facade.customer.ShopCustomerService;
import web.commons.ImagePanel;
import web.error.ProductNotFound;
import web.eshop.panels.CategoryTreePanel;
import web.eshop.panels.CommentsPanel;
import web.eshop.panels.RelatedProductsPanel;

import java.util.List;

/**
 * Display page of selected product.
 */
@MountPath(path = "Product")
@MountIndexedParam
public final class SimpleProductEshopPage extends ShopBasePage {

    private final IModel<Product> productModel;
    @SpringBean
    private ShopCustomerService customerService;
    CategoryTreePanel categoryTreePanel;

    public SimpleProductEshopPage(PageParameters params) {
        try {
            productModel = loadProductModel(params.getAsLong("0"));
            if (productModel.getObject() == null) {
                throw new Exception("produkt nenalezen");
            }
        } catch (Exception e) {
            throw new RestartResponseException(ProductNotFound.class);
        }

        initProductProperties(productModel);
        add(new RelatedProductsPanel("relatedProductPanel", productModel.getObject().getId()));
        add(new CommentsPanel("commentsPanel", productModel));
        showMainProductImage();
        showOtherImages();
    }

    @Override
    protected Component newLeftPanel(String id) {
        return categoryTreePanel = new CategoryTreePanel(id);
    }

    private void showMainProductImage() {
        //Main Image
        IModel<ImageEntry> imageEntryModel = new LoadableDetachableModel<ImageEntry>() {

            @Override
            protected ImageEntry load() {
                return productModel.getObject().getMainImage();
            }
        };
        add(new ImagePanel("mainImage", imageEntryModel));


    }

    private void showOtherImages() {
        LoadableDetachableModel<List<ImageEntry>> imageList =
                new LoadableDetachableModel<List<ImageEntry>>() {

                    @Override
                    protected List<ImageEntry> load() {
                        return productModel.getObject().getImages();
                    }
                };

        WebMarkupContainer container = new WebMarkupContainer("gallery");
        if (imageList.getObject().size() == 0) {
            container.setVisible(false);
        }

        ImageListView imageListView = new ImageListView("images", imageList);
        container.add(imageListView);
        add(container);

    }


    @Override
    public IModel getPageTitle() {
        return new PropertyModel(productModel, "name");
    }

    @Override
    public IModel getDescription() {
        return new PropertyModel(productModel, "description");
    }

    @Override
    public IModel getKeywords() {
        return new PropertyModel(productModel, "keywords");
    }

    private class ImageListView extends ListView<ImageEntry> {

        public ImageListView(String name, final IModel<List<ImageEntry>> files) {
            super(name, files);
        }

        @Override
        protected void populateItem(ListItem<ImageEntry> item) {
            item.add(new ImagePanel("image", item.getModel()));

        }
    }

    private void initProductProperties(final IModel<Product> productModel) {
        add(new Label("name", new PropertyModel(productModel, "name")));
        add(new Label("price", new PropertyModel(productModel, "price")));
        add(new Label("shortContent", new PropertyModel<String>(
                productModel, "shortContent")).setEscapeModelStrings(false));
        add(new Label("content", new PropertyModel<String>(
                productModel, "content")).setEscapeModelStrings(false));
        showAttributes(productModel);

        Form form = new Form("form") {

            private Integer multiplicity = 1;

            private Integer getMultiplicity() {
                return multiplicity;
            }

            private void setMultiplicity(Integer multiplicity) {
                this.multiplicity = multiplicity;
            }

            {
                TextField<Integer> textField = new TextField<Integer>("multiplicity",
                        new PropertyModel<Integer>(this, "multiplicity"));
                textField.setMarkupId("multiplicity");
                textField.setOutputMarkupId(true);
                add(textField.setRequired(true));
            }

            @Override
            protected void onSubmit() {
                if (multiplicity > 0) {
                    customerService.addProductToBasket(productModel.getObject(), multiplicity);
                    info(getLocalizer().getString("product.added", this));
                } else {
                    error(getLocalizer().getString("product.addedFail", this));
                }
            }
        };
        //TODO wtf
//        if (!((WaspSession) getSession()).isUserAuthenticated()) {
//            form.setVisible(false);
//        }
        add(form);
    }

    private void showAttributes(final IModel<Product> productModel) {
        AbstractReadOnlyModel<List<Attribute>> model = new AbstractReadOnlyModel<List<Attribute>>() {

            @Override
            public List<Attribute> getObject() {
                return productModel.getObject().getAttributes();
            }
        };
        ListView listView = new ListView<Attribute>("attributesList", model) {

            @Override
            protected void populateItem(ListItem<Attribute> item) {
                item.add(new Label("aName", new PropertyModel(item, "modelObject.name")));
                item.add(new Label("aValue", new PropertyModel(item, "modelObject.value")));
                item.add(new Label("aUnit", new PropertyModel(item, "modelObject.unit")));
            }
        };
        add(listView);
    }

    private LoadableDetachableModel<Product> loadProductModel(final Long productId) {
        return new LoadableDetachableModel<Product>() {

            @Override
            protected Product load() {
                return customerService.findProductById(productId);
            }
        };
    }
}
